﻿/*
 * File.h
 *
 */
#ifndef __GDK_FILE_H__
#define __GDK_FILE_H__


#include <gdk/core/Types.h>
#include <gdk/core/Archive.h>
#include <gdk/core/String.h>
#include <gdk/core/Time.h>

#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>

#ifdef _WIN32
#	include <io.h>
#endif



namespace gdk
{



class GDK_CORE_EXPORT File : public Archive
{
	DECLARE_CLASS_HANDLE(File)
	DECLARE_CLASS_INSTANCE(File)

public:
	enum
	{
		RDONLY	= O_RDONLY, /* open for reading only */
		WRONLY	= O_WRONLY, /* open for writing only */
		RDWR	= O_RDWR,	/* open for reading and writing */
		APPEND	= O_APPEND,	/* writes done at eof */
		CREATE	= O_CREAT,	/* create and open file */
		TRUNC	= O_TRUNC,	/* open and truncate */
		EXECL	= O_EXCL,	/* open only if file doesn't already exist */
	};

	enum
	{
		S_READ  = 1, /* read permission */
		S_WRITE = 2, /* write permission */
	};

private:
	String	_fileName;
	FILE*	_fp;

protected:
	File(void);
	~File(void);

private:
	__INLINE__ ssize_t tell(bool force = true) const;
	__INLINE__ int seek(ssize_t offset, int origin, bool force = true) const;

public:
	bool open(const String &fileName, int flags, int pmode = S_READ | S_WRITE);
	void close(void);

	__INLINE__ const String& getFileName(void) const { return _fileName; }
	__INLINE__ bool  isInvalid(void) const { return (_fp == NULL); }
	__INLINE__ bool  eof(void) const { return (feof(_fp) != 0); }

public:
	virtual ssize_t getArchiveSize(void) const;
	virtual ssize_t getPosition(void) const;
	virtual ssize_t setPosition(ssize_t pos);

public:
	virtual ssize_t available(void) const;
	virtual ssize_t peek(void *buf, ssize_t size) const;
	virtual ssize_t read(void *buf, ssize_t size);
	virtual ssize_t write(const void *buf, ssize_t size);

public:
	static const Char* getLastError(void);
};


///////////////////////////////////////////
GDK_CORE_EXPORT ssize_t getFileSize(const Char *fileName);
GDK_CORE_EXPORT bool isFileExists(const Char *fileName);
GDK_CORE_EXPORT bool getFileInfo(const Char *fileName, ssize_t &fileSize, Time &ctime, Time &mtime);
GDK_CORE_EXPORT bool calcFileMd5(const Char *fileName, MD5Checksum &checksum);


class TempFile : public File
{
	DECLARE_CLASS_HANDLE(TempFile)
	DECLARE_CLASS_INSTANCE(TempFile)

protected:
	virtual ~TempFile(void);

public:
	GDK_CORE_EXPORT static String getTempFileName(void);
	GDK_CORE_EXPORT static TempFile::Handle createTempFile(void);
};





}//namespace gdk



#endif /*__GDK_FILE_H__*/
